package com.longcai.service.impl.customer;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.longcai.bean.ApiResult;
import com.longcai.bean.GenerateId;
import com.longcai.bean.RedisUtil;
import com.longcai.constants.BaseConstants;
import com.longcai.constants.DicConstants;
import com.longcai.constants.WxConstants;
import com.longcai.entity.customer.ClyjLoginLog;
import com.longcai.entity.customer.ClyjUser;
import com.longcai.entity.customer.ClyjUserTouch;
import com.longcai.entity.sys.ClyjDict;
import com.longcai.mapper.customer.ClyjLoginLogMapper;
import com.longcai.mapper.customer.ClyjUserMapper;
import com.longcai.service.customer.ClyjUserPropertyService;
import com.longcai.service.customer.ClyjUserTouchService;
import com.longcai.service.customer.CustomerService;
import com.longcai.service.dict.ClyjDictService;
import com.longcai.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;

/**
 * @author M
 * @description: TODO
 * @Title: CustomerServiceImpl
 * @date 2019/3/14 10:20
 */
@Service
public class CustomerServiceImpl extends ServiceImpl<ClyjUserMapper, ClyjUser> implements CustomerService {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private ClyjLoginLogMapper clyjLoginLogMapper;
    @Autowired
    private ClyjUserMapper clyjUserMapper;
    @Autowired
    private ClyjUserPropertyService clyjUserPropertyService;
    @Autowired
    private ClyjUserTouchService clyjUserTouchService;
    @Autowired
    private CustomerService customerService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ClyjDictService clyjDictService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 根据名称查询用户信息
     *
     * @param name
     * @return
     */
    @Override
    public ClyjUser getName(String name) {
        try {
            QueryWrapper<ClyjUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("username", name);
            ClyjUser clyjUser = this.clyjUserMapper.selectOne(queryWrapper);
            logger.debug("查询{}", clyjUser);
            return clyjUser;
        } catch (Exception e) {
            logger.error("查询失败");
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 用户注册
     *
     * @param clyjUser
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ApiResult<ClyjUser> customerRegister(ClyjUser clyjUser, String userPId, Integer userPLevel, HttpServletRequest request) {
        try {
            String prefix = "clyj_";
            clyjUser.setLevel(0);
            clyjUser.setUserId(prefix + GenerateId.generateShortUUID());
            clyjUser.setCreateTime(new Date());
            clyjUser.setMemberId(prefix + System.currentTimeMillis());
            clyjUser.setUsername(clyjUser.getUserId());
            clyjUser.setInviteCode(GenerateId.invitationCode());
            clyjUser.setIsAttestation("0");
            clyjUser.setRegistSource("手机号注册");
            //生成个人二维码
            //存放路径
            // 用户主目录
            String realPath = System.getProperties().getProperty("user.home");
            //跳转地址
            String content = " http://clyj.gaojunjun.cn/from/#/login?inviteCode=" + clyjUser.getInviteCode();
            //名称
            String name = "image.jpg";
            File file = QRCodeUtils.testEncode(realPath, content, name);
            if (file != null) {
                //文档上传oss
                try {
                    String pox = name.substring(name.lastIndexOf(".") + 1);
                    InputStream inputStream = new FileInputStream(file);
                    //InputStream inputStream = this.getClass().getResourceAsStream("/qrcode/file");
                    Map<String, Object> uploadByInputStream = OSSUtils.uploadByInputStream(inputStream, pox, "CLYJ/USERCODE/");
                    clyjUser.setCode(uploadByInputStream.get("path").toString());
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            ClyjDict clyjDict = clyjDictService.gerByTypeCode(DicConstants.USER_REGISTEER_POCKET);
            ClyjDict clyjDict1 = clyjDictService.gerByTypeCode(DicConstants.SHARE_USER_POCKET);
            ClyjDict clyjDict2 = clyjDictService.gerByTypeCode(DicConstants.USER_REGISTER);
            ClyjDict clyjDict3 = clyjDictService.gerByTypeCode(DicConstants.USER_REGISTER_INTEGRATION);
            Integer integer = this.clyjUserMapper.insert(clyjUser);
            if (integer > 0) {
                /**资金变动（红包，零钱，积分）TODO_HYF**/
                ApiResult<?> r = clyjUserPropertyService.changeFinance(clyjUser.getUserId(), new BigDecimal(clyjDict.getAttname()), "0", DicConstants.SHARE_USER_POCKET, "0", null, BaseConstants.UNFREEZE, null);
                /**资金变动（红包，零钱，积分）TODO_HYF**/
                ApiResult<?> r1 = clyjUserPropertyService.changeFinance(clyjUser.getUserId(), new BigDecimal(clyjDict2.getAttname()), "0", DicConstants.USER_REGISTER, "1", null, BaseConstants.UNFREEZE, null);
                /**资金变动（红包，零钱，积分）TODO_HYF**/
                ApiResult<?> r2 = clyjUserPropertyService.changeFinance(clyjUser.getUserId(), new BigDecimal(clyjDict3.getAttname()), "0", DicConstants.USER_REGISTER_INTEGRATION, "2", null, BaseConstants.UNFREEZE, null);
                /**资金变动（红包，零钱，积分）TODO_HYF**/
                ApiResult<?> s = clyjUserPropertyService.changeFinance(userPId, new BigDecimal(clyjDict1.getAttname()), "0", DicConstants.SHARE_USER_POCKET, "0", null, BaseConstants.UNFREEZE, null);
                if (!r.getCode().equals("success") || !r1.getCode().equals("success") || !r2.getCode().equals("success") || !s.getCode().equals("success")) {
                    return ApiResult.fail("资产变动失败");
                }
            } else {
                throw new Exception("注册失败");
            }

            //邀请关系
            clyjUserTouchService.saveTouch(userPId, userPLevel, clyjUser, 0);
            //多级邀请关系
            QueryWrapper<ClyjUserTouch> w = new QueryWrapper<ClyjUserTouch>();
            w.eq("user_id", userPId);
            List<ClyjUserTouch> selectList = clyjUserTouchService.selectList(w);
            if (selectList == null || selectList.size() == 0) {
                return ApiResult.fail("注册成功");
            }
            for (ClyjUserTouch clyjUserTouch : selectList) {
                clyjUserTouchService.saveTouch(clyjUserTouch.getUserPId(), clyjUserTouch.getUserPLevel(), clyjUser, clyjUserTouch.getRelationLevel() + 1);
            }
            logger.debug("注册成功");
            return ApiResult.fail("注册成功");
        } catch (Exception e) {
            logger.error("注册失败", e, getClass());
            return ApiResult.fail("注册失败" + e.getMessage());
        }
    }


    /**
     * 根据注册手机号查询是否已注册
     *
     * @param phone
     * @return
     */
    @Override
    public ApiResult isName(String phone) {
        QueryWrapper<ClyjUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", phone);
        List<ClyjUser> list = this.clyjUserMapper.selectList(queryWrapper);
        //判断查询结果
        if (list.size() > 0) {
            return ApiResult.fail("该手机号已被注册");
        } else {
            return ApiResult.success("该手机号可以注册");
        }

    }

    /**
     * 查询用户登录信息
     *
     * @param phone
     * @param pwd
     * @param request
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ApiResult customerLogin(String phone, String pwd, HttpServletRequest request) {
        try {
            ClyjUser clyjUser = this.clyjUserMapper.selectuserinfo(phone);
            if (clyjUser == null) {
                return ApiResult.fail("账号错误");
            }
            boolean matches = passwordEncoder().matches(pwd, clyjUser.getPassword());
            if (matches) {
                //返回token
                String webtoken = UUID.randomUUID().toString();
                if (webtoken != null) {
                    //redis存入token和用户信息
                    Long aLong = new Long(60 * 60 * 1000 * 24 * 7);
                    redisUtil.set(webtoken, clyjUser, aLong);
                    return ApiResult.success(webtoken);
                }
                logger.debug("查询成功");
            } else {
                logger.debug("查询失败");
                return ApiResult.fail("用户或者密码错误");
            }
        } catch (Exception e) {
            logger.debug("查询失败");
            e.printStackTrace();
            return ApiResult.fail("查询失败" + e.getMessage());
        }
        return null;
    }

    /**
     * 微信授权登录
     *
     * @param request
     * @param response
     */
    @Override
    public void wxLogin(HttpServletRequest request, HttpServletResponse response) {
        try {
            String authUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WxConstants.APPID
                    + "&redirect_uri=" + URLEncoder.encode(WxConstants.REDIRECT_URL, "GBK")
                    + "&response_type=code"
                    + "&scope=snsapi_userinfo"
                    + "&connect_redirect=1"
                    + "&state=STATE#wechat_redirect";

            // 微信加密签名
            String signature = request.getParameter("signature");
            // 时间戳
            String timestamp = request.getParameter("timestamp");
            // 随机数
            String nonce = request.getParameter("nonce");
            // 随机字符串
            String echostr = request.getParameter("echostr");
            response.sendRedirect(authUrl);
        } catch (IOException e) {
            throw new RuntimeException("微信授权失败" + e.getMessage());
        }
    }

    /**
     * 微信授权成功回调
     *
     * @param request
     * @param respons
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public String wxCallBack(HttpServletRequest request, HttpServletResponse respons) {

        try {
            // start 获取微信用户基本信息
            String code = request.getParameter("code");
            //通过code换取网页授权access_token
            String access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + WxConstants.APPID
                    + "&secret=" + WxConstants.APPSECRET
                    + "&code=" + code
                    + "&grant_type=authorization_code";
            //发送请求
            JSONObject jsonResult = HttpClientUtil.get(access_token_url);
            logger.info("微信——————————jsonResult" + jsonResult.toString());
            JSONObject accessJsonObject = jsonResult.getJSONObject("response");
            if (accessJsonObject == null || accessJsonObject.getInteger("errcode") != null || accessJsonObject.getString("openid") == null) {
                logger.debug("微信连接异常");
                throw new RuntimeException("微信连接异常");
            }

            //与开放平台关联要使用unionid
            String openid = accessJsonObject.getString("openid");
            logger.info("微信——————————openid" + openid);
            String access_token = accessJsonObject.getString("access_token");
            logger.info("微信——————————access_token" + access_token);

            /**
             * 获取用户的微信信息(需scope为 snsapi_userinfo)
             */
            String infoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token
                    + "&openid=" + openid
                    + "&lang=zh_CN";
            JSONObject userInfoJson = HttpClientUtil.get(infoUrl);
            //使用微信的信息
            JSONObject userInfoJsonObject = userInfoJson.getJSONObject("response");
            if (userInfoJsonObject == null || "".equals(userInfoJsonObject)) {
                logger.debug("获取用户微信信息失败");
                throw new Exception("获取用户微信信息失败");
            }
            /**
             * 微信与用户信息的绑定
             */
            QueryWrapper<ClyjUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("openid", openid);
            ClyjUser clyjUser1 = clyjUserMapper.selectOne(queryWrapper);
            ClyjUser clyjUser = new ClyjUser();
            Map map = new HashMap();
            map.put("openid", openid);
            String wxtoken = UUID.randomUUID().toString();
            //设置过期时间
            Long aLong = new Long(60 * 60 * 1000 * 24 * 7);
            if (clyjUser1 == null) {
                logger.debug("该账号暂未注册");
                String icon = userInfoJsonObject.getString("headimgurl");
                logger.debug("<<<<<<<<<---json--->>>>>>>>>>" + userInfoJsonObject.toString());
                logger.debug("<<<<<<<<<---头像--->>>>>>>>>>" + icon);
                map.put("icon", icon);
                redisUtil.set(wxtoken, map, aLong);
                logger.debug("微信没注册跳到注册");
                return "redirect:"+ WxConstants.WXFAILURL + wxtoken;
            } else {
                redisUtil.set(wxtoken, clyjUser1, aLong);
                logger.debug("微信已注册跳到个人中心");
                return "http://clyj.gaojunjun.cn/from/#/me?token=" + wxtoken;
            }
        } catch (Exception e) {
            throw new RuntimeException("微信授权失败");
        }

    }


    /**
     * 微信登录注册
     *
     * @param code
     * @param phone
     * @param inviteCode
     * @param openid
     * @param icon
     * @param token
     * @param pwd
     * @param request
     * @return
     */
    @Override
    public ApiResult wxRegister(String code, String phone, String inviteCode, String openid, String icon, String token, String pwd, String userPid, HttpServletRequest request) {
        try {
            //微信登录用户绑定手机号注册
            ClyjUser clyjUser = new ClyjUser();
            String prefix = "clyj_";
            clyjUser.setLevel(0);
            clyjUser.setPassword(passwordEncoder().encode(pwd));
            clyjUser.setUserId(prefix + GenerateId.generateShortUUID());
            clyjUser.setCreateTime(new Date());
            clyjUser.setMemberId(prefix + System.currentTimeMillis());
            clyjUser.setUsername(clyjUser.getUserId());
            clyjUser.setInviteCode(GenerateId.invitationCode());
            clyjUser.setIsAttestation("0");
            clyjUser.setPhone(phone);
            clyjUser.setOpenid(openid);
            clyjUser.setPhoto(icon);
            clyjUser.setRegistSource("微信注册");
            //生成个人二维码
            //存放路径
            // 用户主目录
            String realPath = System.getProperties().getProperty("user.home");
            //跳转地址
            String content = " http://clyj.gaojunjun.cn/from/#/login?inviteCode=" + clyjUser.getInviteCode();
            //名称
            String name = "image.jpg";
            File file = QRCodeUtils.testEncode(realPath, content, name);
            if (file != null) {
                //文档上传oss
                try {
                    String pox = name.substring(name.lastIndexOf(".") + 1);
                    InputStream inputStream = new FileInputStream(file);
                    //InputStream inputStream = this.getClass().getResourceAsStream("/qrcode/file");
                    Map<String, Object> uploadByInputStream = OSSUtils.uploadByInputStream(inputStream, pox, "CLYJ/USERCODE/");
                    clyjUser.setCode(uploadByInputStream.get("path").toString());
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            Integer integer = this.clyjUserMapper.insert(clyjUser);

            ClyjDict clyjDict = clyjDictService.gerByTypeCode(DicConstants.USER_REGISTEER_POCKET);
            ClyjDict clyjDict1 = clyjDictService.gerByTypeCode(DicConstants.SHARE_USER_POCKET);
            ClyjDict clyjDict2 = clyjDictService.gerByTypeCode(DicConstants.USER_REGISTER);
            ClyjDict clyjDict3 = clyjDictService.gerByTypeCode(DicConstants.USER_REGISTER_INTEGRATION);
            if (integer > 0) {
                /**资金变动（红包，零钱，积分）TODO_HYF**/
                ApiResult<?> r = clyjUserPropertyService.changeFinance(clyjUser.getUserId(), new BigDecimal(clyjDict.getAttname()), "0", DicConstants.SHARE_USER_POCKET, "0", null, BaseConstants.UNFREEZE, null);
                /**资金变动（红包，零钱，积分）TODO_HYF**/
                ApiResult<?> r1 = clyjUserPropertyService.changeFinance(clyjUser.getUserId(), new BigDecimal(clyjDict2.getAttname()), "0", DicConstants.USER_REGISTER, "1", null, BaseConstants.UNFREEZE, null);
                /**资金变动（红包，零钱，积分）TODO_HYF**/
                ApiResult<?> r2 = clyjUserPropertyService.changeFinance(clyjUser.getUserId(), new BigDecimal(clyjDict3.getAttname()), "0", DicConstants.USER_REGISTER_INTEGRATION, "2", null, BaseConstants.UNFREEZE, null);
                /**资金变动（红包，零钱，积分）TODO_HYF**/
                ApiResult<?> s = clyjUserPropertyService.changeFinance(userPid, new BigDecimal(clyjDict1.getAttname()), "0", DicConstants.SHARE_USER_POCKET, "0", null, BaseConstants.UNFREEZE, null);
                if (!r.getCode().equals("success") || !r1.getCode().equals("success") || !r2.getCode().equals("success") || !s.getCode().equals("success")) {
                    return ApiResult.fail("资产变动失败");
                }
            } else {
                throw new Exception("注册失败");
            }
            //放入redis返回前台
            redisUtil.set(token, clyjUser);
            return ApiResult.success(token);
        } catch (Exception e) {
            e.printStackTrace();
            return ApiResult.fail("注册失败" + e.getMessage());
        }
    }


    /**
     * 登录日志
     *
     * @param clyjUser
     * @param request
     */
    public void LoginLog(ClyjUser clyjUser, HttpServletRequest request) {
        ClyjLoginLog clyjLoginLog = new ClyjLoginLog();
        //存储登录日志
        clyjLoginLog.setCustomerName(clyjUser.getUsername());
        clyjLoginLog.setCustomerId(clyjUser.getUserId());
        clyjLoginLog.setCTime(new Date());
        clyjLoginLog.setIp(IpUtils.getIpAddr(request));
        this.clyjLoginLogMapper.insert(clyjLoginLog);
    }

    /**
     * 修改绑定手机号
     *
     * @param phone
     * @param newphone
     * @return
     */
    @Override
    public ApiResult updatePhone(String phone, String newphone) {
        try {
            QueryWrapper<ClyjUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("phone", phone);
            //判断字符串
            ClyjUser clyjUser = this.clyjUserMapper.selectOne(queryWrapper);
            if (clyjUser == null) {
                return ApiResult.fail("手机号与登录用户不匹配");
            } else {
                clyjUser.setPhone(newphone);
            }
            clyjUser.setUpdateTime(new Date());
            Integer i = clyjUserMapper.update(clyjUser, queryWrapper);
            logger.info("更改成功", i);
            return ApiResult.success(i);

        } catch (Exception e) {
            logger.error("更改失败");
            e.printStackTrace();
            return ApiResult.fail("查询失败" + e.getMessage());
        }
    }

    /**
     * 修改登录密码
     *
     * @param phone
     * @param pwd
     * @return
     */
    @Override
    public ApiResult updatePwd(String phone, String pwd) {
        try {
            QueryWrapper<ClyjUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("phone", phone);
            //判断字符串
            ClyjUser clyjUser = this.clyjUserMapper.selectOne(queryWrapper);
            if (clyjUser == null) {
                return ApiResult.fail("手机号与登录用户不匹配");
            } else {
                clyjUser.setPassword(passwordEncoder().encode(pwd));
            }
            clyjUser.setUpdateTime(new Date());
            Integer i = clyjUserMapper.update(clyjUser, queryWrapper);
            logger.info("更改成功", i);
            return ApiResult.success(i);
        } catch (Exception e) {
            logger.error("更改失败");
            e.printStackTrace();
            return ApiResult.fail("查询失败" + e.getMessage());
        }
    }

    /**
     * 修改支付密码
     *
     * @param phone
     * @param newpayPwd
     * @return
     */
    @Override
    public ApiResult updatePaypwd(String phone, String newpayPwd) {
        try {
            QueryWrapper<ClyjUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("phone", phone);
            //判断字符串
            ClyjUser clyjUser = this.clyjUserMapper.selectOne(queryWrapper);
            if (clyjUser == null) {
                return ApiResult.fail("手机号与登录用户不匹配");
            } else {
                clyjUser.setPayPwd(passwordEncoder().encode(newpayPwd));
            }
            clyjUser.setUpdateTime(new Date());
            Integer i = clyjUserMapper.update(clyjUser, queryWrapper);
            logger.info("更改成功", i);
            return ApiResult.success(i);
        } catch (Exception e) {
            logger.error("更改失败");
            e.printStackTrace();
            return ApiResult.fail("查询失败" + e.getMessage());
        }
    }

    /**
     * 设置支付密码
     *
     * @param phone
     * @param payPwd
     * @return
     */
    @Override
    public ApiResult setPayPwd(String phone, String payPwd) {
        try {
            QueryWrapper<ClyjUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("phone", phone);
            //判断字符串
            ClyjUser clyjUser = this.clyjUserMapper.selectOne(queryWrapper);
            if (clyjUser == null) {
                return ApiResult.fail("手机号与登录用户不匹配");
            } else {
                clyjUser.setPayPwd(passwordEncoder().encode(payPwd));
            }
            Integer i = this.clyjUserMapper.update(clyjUser, queryWrapper);
            logger.debug("设置成功");
            return ApiResult.success(i);
        } catch (Exception e) {
            logger.error("设置失败");
            e.printStackTrace();
            return ApiResult.fail("查询失败" + e.getMessage());
        }
    }

    /**
     * 个人信息
     *
     * @param token
     * @return
     */
    @Override
    public ApiResult perInformation(String token, HttpServletRequest request) {
        try {
            boolean b = redisUtil.exists(token);
            if (b) {
                ClyjUser clyjUser = (ClyjUser) redisUtil.get(token);
                logger.debug("查询成功");
                LoginLog(clyjUser, request);
                return ApiResult.success(clyjUser);
            }
        } catch (Exception e) {
            logger.error("查询失败");
            e.printStackTrace();
            return ApiResult.fail("查询失败" + e.getMessage());
        }
        return null;
    }

    /**
     * 微信信息
     *
     * @param token
     * @param request
     * @return
     */
    @Override
    public ApiResult perInformations(String token, HttpServletRequest request) {
        try {
            boolean b = redisUtil.exists(token);
            if (b) {
                Map map = (Map) redisUtil.get(token);
                logger.debug("查询成功");
                return ApiResult.success(map);
            }
        } catch (Exception e) {
            logger.error("查询失败");
            e.printStackTrace();
            return ApiResult.fail("查询失败" + e.getMessage());
        }
        return null;
    }


}
